package rap

import (
	data2 "api_online/data"
	"encoding/json"
	"sort"
	"strings"
)

var dataRap dataJson

type dataJson struct{
	Data data `json:"data"`
}

// 整体数据
type data struct {
	Name string        `json:"name"`
	Description string `json:"description"`
	Modules []module   `json:"modules"`
}

// 模块-文件
type module struct {
	Name string        `json:"name"`
	Description string `json:"description"`
	Interfaces []api   `json:"interfaces"`
}

// 接口
type api struct {
	Name        string    `json:"name"`
	Url         string    `json:"url"`
	Method      string    `json:"method"`
	BodyOption  string    `json:"bodyOption"`
	Description string    `json:"description"`
	Status      int       `json:"status"`
	Properties []property `json:"properties"`
}

// 参数/返回值
type property struct {
	Id          int    `json:"id"`
	ParentId    int    `json:"parentId"`
	Scope       string `json:"scope"`
	Type        string `json:"type"`
	Pos         int    `json:"pos"`
	Name        string `json:"name"`
	Value       string `json:"value"`
	Description string `json:"description"`
	Required    bool   `json:"required"`
}

// 临时使用
type resultListStruct struct {
	Key string
	Val interface{}
}

const bodyOptionRaw = "RAW"
const scopeRequest = "request"
const scopeResponse = "response"
const typeString = "String"
const typeArray = "Array"
const typeObj = "Object"
const parentIdDefault = -1
const posThree = 3

func init() {
	dataRap = dataJson{}
}

func Rap() []byte {
	cache := data2.Cache
	idNow := 1
	dataData := data{
		Name: "仓库",
		Description: "仓库描述",
	}
	// 获取文件当做模块
	fileList := cache.GetSyntaxFileList()

	for _, v := range fileList {
		moduleData := module{
			Name: v.Desc,
			Description: v.Desc,
			Interfaces: []api{},
		}
		// 获取文件内的接口
		apiList := cache.GetFileInfo(v.FileName)
		for _, vApi := range apiList {
			apiData := api{
				Name:        vApi.Desc,
				Url:         "/" + vApi.Url,
				Method:      vApi.Method,
				BodyOption:  bodyOptionRaw,
				Description: vApi.Desc,
				Status:      200,
				Properties:  []property{},
			}

			// 获取接口内参数
			paramList := vApi.Param
			for _, vParam := range paramList {
				param := property{
					Id:          idNow,
					Name:        vParam.Key,
					Description: vParam.Name,
					ParentId:    parentIdDefault,
					Scope:       scopeRequest,
					Type:        typeString,
					Pos:         posThree,
					Value:       vParam.Default,
					Required:    true,
				}
				idNow++
				apiData.Properties = append(apiData.Properties, param)
			}

			// 获取返回值
			resultList := cache.GetResultCacheByUrl(vApi.Url)
			resultResList := getResultRes(resultList, idNow)
			apiData.Properties = append(apiData.Properties, resultResList...)

			moduleData.Interfaces = append(moduleData.Interfaces, apiData)
		}
		dataData.Modules = append(dataData.Modules, moduleData)
	}
	dataRap.Data = dataData
	dataRapJson, err := json.Marshal(dataRap)
	if err != nil {
		panic(err)
	}

	return dataRapJson
}


func getResultRes(resultList map[string]interface{}, idNow int) []property {
	// 按key的长度排序
	var resultListArr []*resultListStruct
	for k, v := range resultList {
		resultListArr = append(resultListArr, &resultListStruct{
			Key: k,
			Val: v,
		})
	}
	// 先按字母排序
	resultListArr = sortByKey(resultListArr)
	// 再按.和:的数量排序
	sort.Slice(resultListArr, func(i, j int) bool {
		iKeyLen := strings.Count(resultListArr[i].Key, ".") + strings.Count(resultListArr[i].Key, ":")
		jKeyLen := strings.Count(resultListArr[j].Key, ".") + strings.Count(resultListArr[j].Key, ":")

		return iKeyLen < jKeyLen
	})

	keyIdMap := map[string]int{}
	resultResList := []property{}
	for _, v := range resultListArr {
		kResult := v.Key
		vResult := v.Val
		parentId := parentIdDefault
		pre, key := getPreAndChildByStr(kResult)

		// 判断前缀的子串是否在map中
		preVal, ok := keyIdMap[pre]
		if ok {
			// 如果存在, 则赋值父ID,
			parentId = preVal
		}

		keyIdMap[kResult] = idNow

		// type, 判断下一个元素中是否含有 x: 或者 x.
		typeVal := typeString
		kResultNext := getMapNextHasNow(resultList, kResult, ":")
		if kResultNext {
			typeVal = typeArray
		}
		kResultNext = getMapNextHasNow(resultList, kResult, ".")
		if kResultNext {
			typeVal = typeObj
		}

		result := property{
			Id:          idNow,
			Name:        key,
			Description: vResult.(string),
			ParentId:    parentId,
			Scope:       scopeResponse,
			Type:        typeVal,
			Pos:         posThree,
			Value:       "",
			Required:    true,
		}
		idNow++

		resultResList = append(resultResList, result)
	}
	return resultResList
}

// 从字符串中获取前缀与子串
func getPreAndChildByStr(str string) (string, string) {
	pre := ""
	key := ""
	byte := []byte(str)
	sStrTmp := ""
	for _, s := range byte {
		sStr := string(s)

		// 往key中加
		if sStr != "." && sStr != ":" {
			key += sStr
		} else {
			// 遇到分隔符.说明此时的key还不是key.放入前缀中.key清空,暂存分隔符
			pre += sStrTmp + key
			sStrTmp = sStr
			key = ""
		}
	}

	return pre, key
}

func getMapNextHasNow(resultList map[string]interface{}, kResult string, key string) bool {
	keyCheck := kResult + key
	for k, _ := range resultList {
		if strings.Contains(k, keyCheck) {
			return true
		}
	}
	return false
}

// 按字母顺序遍历map
func sortByKey(params []*resultListStruct) []*resultListStruct {
	keys := make([]string, 0)
	data := map[string]*resultListStruct{}
	for _, line := range(params) {
		keys = append(keys, line.Key)
		data[line.Key] = line
	}
	sort.Strings(keys)
	res := []*resultListStruct{}
	for _, k := range keys {
		res = append(res, data[k])
	}
	return res
}